package com.sluggard.workflow.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sluggard.common.exception.BusinessException;
import com.sluggard.common.model.res.Result;
import com.sluggard.workflow.entity.res.ProcessDefinitionResponse;
import com.sluggard.workflow.entity.res.ProcessInstanceResponse;
import com.sluggard.workflow.model.dto.ProcessInstanceStartDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.camunda.bpm.engine.RepositoryService;
import org.camunda.bpm.engine.RuntimeService;
import org.camunda.bpm.engine.repository.ProcessDefinition;
import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.camunda.bpm.engine.runtime.ProcessInstanceQuery;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Tag(name = "工作流-流程实例管理")
@RestController
@RequestMapping("workflow/runtime/processInstance")
public class ProcessInstanceController {

    @Resource
    private RuntimeService runtimeService;

    @Resource
    private RepositoryService repositoryService;

    @Operation(summary = "启动流程实例")
    @PostMapping("/start")
    public Result<String> startProcess(@RequestBody ProcessInstanceStartDTO startDTO) {
        try {
            startDTO.getVariables().put("${applicant}", startDTO.getUser());
            ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(
                    startDTO.getProcessDefinitionKey(),
                    startDTO.getBusinessKey(),
                    startDTO.getVariables()
            );
            return Result.ok(processInstance.getId());
        } catch (Exception e) {
            log.error("启动流程实例失败", e);
            throw new BusinessException("启动流程实例失败");
        }
    }

    @Operation(summary = "查询流程实例")
    @GetMapping("/list")
    public Result<Page<ProcessInstanceResponse>> list(
            @RequestParam("pageNo") Integer pageNo,
            @RequestParam("pageSize") Integer pageSize,
            @RequestParam(value = "processDefinitionKey", required = false) String processDefinitionKey,
            @RequestParam(value = "businessKey", required = false) String businessKey) {

        ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery();
        if (StringUtils.isNotBlank(businessKey)) {
            query.processInstanceBusinessKeyLike("%" +businessKey+ "%");
        }
        if (StringUtils.isNotBlank(processDefinitionKey)) {
            query.processDefinitionKey(processDefinitionKey);
        }
        List<ProcessInstance> instances = query
                .orderByProcessInstanceId().desc()
                .listPage((pageNo - 1) * pageSize, pageSize);

        Page<ProcessInstanceResponse> page = new Page<>();
        page.setRecords(instances.parallelStream()
                .map(instance -> {
                    ProcessInstanceResponse processInstanceResponse = new ProcessInstanceResponse();
                    BeanUtils.copyProperties(instance, processInstanceResponse);
                    // 绑定流程定义
                    ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                            .processDefinitionId(instance.getProcessDefinitionId())
                            .singleResult();
                    ProcessDefinitionResponse processDefinitionResponse = new ProcessDefinitionResponse();
                    BeanUtils.copyProperties(processDefinition, processDefinitionResponse);
                    processInstanceResponse.setProcessDefinition(processDefinitionResponse);
                    Map<String, Object> variables = runtimeService.getVariables(instance.getId());
                    if(!CollectionUtils.isEmpty(variables)){
                        variables.forEach((key, value) -> {
                                processInstanceResponse.getVariableMap().put(key, value);
                        });
                    }
                    return processInstanceResponse;
                }).toList());
        page.setCurrent(pageNo);
        page.setSize(pageSize);
        page.setTotal(query.count());


        return Result.ok(page);
    }

    @Operation(summary = "删除流程实例")
    @DeleteMapping("/{processInstanceId}")
    public Result<Void> deleteProcessInstance(
            @PathVariable String processInstanceId,
            @RequestParam(required = false) String deleteReason) {
        try {
            runtimeService.deleteProcessInstance(processInstanceId, deleteReason);
            return Result.ok();
        } catch (Exception e) {
            log.error("删除流程实例失败", e);
            throw new BusinessException("删除流程实例失败");
        }
    }

    @Operation(summary = "挂起流程实例")
    @PutMapping("/{processInstanceId}/suspend")
    public Result<Void> suspendProcessInstance(@PathVariable String processInstanceId) {
        try {
            runtimeService.suspendProcessInstanceById(processInstanceId);
            return Result.ok();
        } catch (Exception e) {
            log.error("挂起流程实例失败", e);
            throw new BusinessException("挂起流程实例失败");
        }
    }

    @Operation(summary = "激活流程实例")
    @PutMapping("/{processInstanceId}/activate")
    public Result<Void> activateProcessInstance(@PathVariable String processInstanceId) {
        try {
            runtimeService.activateProcessInstanceById(processInstanceId);
            return Result.ok();
        } catch (Exception e) {
            log.error("激活流程实例失败", e);
            throw new BusinessException("激活流程实例失败");
        }
    }
} 